home *** CD-ROM | disk | FTP | other *** search
/ BBS in a Box 7 / BBS in a Box - Macintosh - Volume VII (BBS in a Box) (January 1993).iso / Files / Prog / M / MacRecorder® HackersToolkit.cpt / Sound.c < prev    next >
Text File  |  1989-12-07  |  8KB  |  335 lines

  1. /* Copyright © 1989  Farallon Computing, Inc */
  2.  
  3. #include    "Sound.h"
  4.  
  5. #define        NIL             0
  6. #define        Snd2HeaderSize    36
  7. #define        K                 1024        /* 1024 bytes per K */
  8.  
  9. void    InitMac( void);
  10. short    Record( Handle, short);
  11. Handle    GetBigHandle( short);
  12.  
  13. long    Mono22Khz( char*, Ptr, char*, long);
  14. void    BuildSoundHeader( Handle);
  15. void    FillInNumSample(    Handle, long);
  16. void    Interrupts( short );
  17. void    SCCPort( short, char**, char** );
  18. void    SCCPoke( char*, short, short );
  19. void    SCCInit( char*);
  20. void    BuildFlipTable( char*);
  21. short    Flip( short);
  22.  
  23. /*
  24. **    Geneal function to initialize the managers
  25. */
  26. void    InitMac()
  27. {
  28.     register     short    i;
  29.                 Ptr        p;
  30.     
  31.     asm 
  32.     {
  33.         MOVE.L    SP,A0                    ; current stack pointer to A0
  34.         SUB        #0x4000,A0                ; allow it to expand 16K lower
  35.         MOVE.L    A0,p
  36.     }
  37.     
  38.     SetApplLimit( p );
  39.     MaxApplZone();    /* grow the Application's heap zone to its limit */
  40.  
  41.     /*
  42.     **    Initialize all managers through the Window Manager here,
  43.     **    rather than in our initialization segment, because
  44.     **    InitWindows allocates non-relocatables.  We don't want
  45.     **    those non-relocatables allocated above the initialization
  46.     **    segment which will be loaded low by the 64K ROM segment
  47.     **    loader.  The remaining managers are initialized from our
  48.     **    initialization segment.
  49.     */
  50.     InitGraf( &thePort );
  51.     InitFonts();
  52.     InitWindows();
  53.  
  54.     /*
  55.         Call MoreMasters here because it allocates non-relocatables.
  56.     */
  57.     for (i=0;i<6;i++) MoreMasters();
  58.     InitMenus();
  59.     InitDialogs( NIL );
  60.     TEInit();
  61.     
  62.     InitCursor();    /* arrow cursor */
  63. }
  64.  
  65. /*
  66. **    Records a sound into the sound Handle
  67. **    Builds a header around the sound to make it a snd2 format
  68. **    If recording fails, returns recordErr ( = -1)
  69. **    Recording stops when memory runs out OR the mouse 
  70. **    is clicked (or moved on MacII or more recent models)
  71. **
  72. **    We record a mono sound at 22Khz
  73. */
  74. short    Record( soundHandle, whichPort)
  75.     Handle        soundHandle;
  76.     short        whichPort;
  77. {
  78.     char*         writePort;
  79.     char*        readPort; 
  80.     unsigned     char     table[256 + 1];
  81.     long        size = GetHandleSize( soundHandle);
  82.     long        len;
  83.     
  84.     /* the handle is too small to even accomodate the header */
  85.     if (size < Snd2HeaderSize)
  86.         return( recordErr);
  87.         
  88.     /* initialize MacRecorder */
  89.     SCCPort( whichPort, &readPort, &writePort );
  90.     SCCInit( writePort );
  91.     BuildFlipTable( (char *)table );
  92.     
  93.     BuildSoundHeader( soundHandle);        /* builds snd2 header */
  94.     
  95.     HLock( soundHandle);
  96.     Interrupts( false );    /* turn interrupts off */
  97.     /* actually record it here */
  98.     len = Mono22Khz( readPort, (Ptr)(*soundHandle + Snd2HeaderSize), 
  99.                         (char *)table, size - Snd2HeaderSize );
  100.     Interrupts( true );        /* turn interrupts back on */
  101.     HUnlock( soundHandle);    
  102.     
  103.     if (len == -1)
  104.     {
  105.         /* could not record */
  106.         return( recordErr);
  107.     }
  108.     else
  109.     {
  110.         /* fills header with # samples */
  111.         FillInNumSample( soundHandle, len);                
  112.         SetHandleSize( soundHandle, len + Snd2HeaderSize);    /* shrink the handle */
  113.         return( noErr);
  114.     }
  115. }
  116.  
  117. /*
  118. **    Allocate the largest possible handle
  119. **    while leaving the  given number of K
  120. **    available
  121. */
  122. Handle    GetBigHandle(    leaveThis)
  123.     short    leaveThis;
  124. {
  125.     long    maxLength;
  126.     Handle    reserveHandle;
  127.     Handle    bigHandle;
  128.     
  129.     reserveHandle = NewHandle( leaveThis*K);
  130.     if (reserveHandle == 0)
  131.         return( 0);    /* we don't even HAVE the memory we want to reserve */    
  132.         
  133.     /* allocate largest possible handle now */        
  134.     maxLength = CompactMem( 0x7FFFFFFFL);
  135.     bigHandle =  NewHandle( maxLength);
  136.     
  137.     DisposHandle( reserveHandle);    /* release memory we were reserving */
  138.     return( bigHandle);
  139. }
  140.  
  141. static    void    SCCInit( scc )
  142.     char *scc;
  143. {
  144.     Interrupts( false );            /* turn off interupts */
  145.     SCCPoke(scc,9,2);                /* NV only */
  146.     SCCPoke(scc,4,12);                /* 2 stop bits, Async, x16 clock mode */
  147.     SCCPoke(scc,1,1);                /* no Rx/Tx Int, Ext Int ON (mouse) */
  148.     SCCPoke(scc,3,193);                /* initialize receiver, 8bits */
  149.     SCCPoke(scc,5,122);                /* 8bits/char, send break(for other hardware!), Tx enable */
  150.     SCCPoke(scc,11,48);                /* use TRxC as receiver clock */
  151.     SCCPoke(scc,14,1);                /* BR enable, nothing else */
  152.     SCCPoke(scc,15,8);                /* Interrupt on CD changes (mouse), turn off CTS interrupt */
  153.     SCCPoke(scc,64,64);                /* Reset Rx CRC */
  154.     SCCPoke(scc,9,10);                /* initialize master interrupt and NV */
  155.     Interrupts( true );                /* turn on interrupts */
  156. }
  157.  
  158. static    void    SCCPoke( scc, reg, value )
  159.     char     *scc;
  160.     short    reg, value;
  161. {
  162.     *scc = reg;
  163.     *scc = value;
  164. }
  165.  
  166.  
  167. static    void    SCCPort( whichPort, read, write )
  168.     short    whichPort;
  169.     char    **read, **write;
  170. {
  171.      *read = SCCRd;
  172.     *write = SCCWr;
  173.     if (whichPort == modemPort) 
  174.     {
  175.         *read += 2;
  176.         *write += 2;
  177.     }
  178. }
  179.                 
  180. /*
  181. **    Data comes out of the MacRecorder with the bits of each
  182. **    byte in the wrong order.  So, we must flip each byte to
  183. **    get it in the right order.  Instead of doing this on the
  184. **    fly, we build a table that has an entry for each value
  185. **    a byte can have and which gives the flip value for each
  186. **    entry
  187. */
  188. static    void    BuildFlipTable( p )
  189.     register char *p;
  190. {
  191.     register short    i;
  192.     
  193.     for (i=0; i<256; i++) 
  194.         p[i] = Flip(i);
  195. }
  196.  
  197. /* flips a byte (byte 0 becomes byte 7, etc.) */
  198. static    short Flip( x )
  199.     short    x;
  200. {
  201.     asm 
  202.     {
  203.         MOVEM.L        D1-D2,-(A7)        ; save on stack
  204.         MOVE        x,D1            ; value we want to flip
  205.         MOVEQ        #7,D2            ; loop though 8 bits
  206.         MOVEQ        #0,D0            ; our result
  207. @0
  208.         ROXL.B        #1,D1            ; get bit n from source
  209.         ROXR.B        #1,D0            ; roll into MSB of dest
  210.         DBRA        D2,@0            ; are we done?
  211.                                     ; D0 contains flipped value
  212.         MOVEM.L        (A7)+,D1-D2        ; retrieve saved registers
  213.     }
  214. }
  215.  
  216. /*
  217. **    Record a Mono sound at 22KHz
  218. **    len = maximum length for the sound
  219. */
  220. static    long Mono22Khz(fromWhere, outBuff, flipTable, len )
  221.     char*    fromWhere;
  222.     Ptr        outBuff;
  223.     char*    flipTable;
  224.     long    len;
  225. {
  226.     asm 
  227.     {
  228.         MOVEM.L        A2-A4/D2-D7,-(SP)    ; save regs
  229.  
  230.         MOVE.L        fromWhere,A4        ; get SCC
  231.         MOVE.L        outBuff,A3            ; get dest buffer
  232.         MOVE.L        flipTable,A2        ; get trans table
  233.         MOVE.L        len,D6                ; get buffer max
  234.  
  235.         MOVEQ        #-1,D0                ; result code - assume the worst
  236.  
  237.         MOVE.L        VIA,A0                ; mouse address from VIA
  238.         MOVEQ        #0,D2                ; byte holder
  239.         MOVE.L        D6,D1                ; save byte count
  240. @reset
  241.         MOVE        #50000,D7             ; watchdog timer
  242. @loop
  243.         SUBQ.L        #1,D7                ; decrement watchdog
  244.         BMI.S        @timeOut
  245.  
  246.         BTST        #3,(A0)                ; mouse button abort?
  247.         BEQ.S        @exit    
  248.  
  249.         BTST        #0,(A4)                ; test and wait for data from SCC
  250.         BEQ.S        @loop                ; not yet
  251.  
  252.         MOVE.B        4(A4),D2            ; get the data
  253.         MOVE.B        0(A2,D2),(A3)+        ; stuff away
  254.  
  255.         SUBQ.L        #1,D6
  256.         BNE.S        @reset
  257. @exit
  258.         SUB.L        D6,D1                ; get actual byte count
  259.         MOVE.L        D1,D0                ; and return it
  260. @timeOut
  261.         MOVEM.L        (SP)+,A2-A4/D2-D7    ; restore regs
  262.     }
  263. }
  264.             
  265.             
  266. /*
  267. **    Takes a handle and fills in the memory at the handle
  268. **    with a Snd2 resource header
  269. */
  270. static    void    BuildSoundHeader( soundHandle)
  271.     Handle        soundHandle;
  272. {
  273.     asm
  274.     {
  275.         MOVE.L        A0, -(A7)            ; save regsiter
  276.         MOVE.L        soundHandle, A0        ; handle to data
  277.         MOVE.L        (A0),A0                ; dereference
  278.         MOVE        #2,(A0)                ; format 2 resource
  279.         MOVE        #1,4(A0)            ; 1 sound command to follow
  280.         
  281.         /* first command, 8 bytes in length */
  282.         MOVE        #0x8051,6(A0)        ; bufferCmd, high bit on to indicate sound
  283.                                         ; data included
  284.         MOVE        #0,8(A0)            ; bufferCmd param1
  285.         MOVE.L        #20,10(A0)            ; bufferCmd param2,
  286.                                         ; offset to sound header
  287.                                         
  288.         /* sampled sound header used in a soundCmd and bufferCmd */
  289.         MOVE.L        #0,14(A0)            ; ptr to data
  290.                                         ; (it follows immediately)
  291.         MOVE.L        #0,18(A0)            ; number of samples
  292.                                         ; (gets filled in later)
  293.         MOVE.L        #0x56EE8BA3,22(A0)    ; sampling rate (22kHz)
  294.         MOVE.L        #0,26(A0)            ; starting of sample's loop point
  295.         MOVE.L        #0,30(A0)            ; ending of sample's loop point
  296.         MOVE.B        #0,34(A0)            ; standard sample encoding
  297.         MOVE.B        #0x3C,35(A0)        ; base note (middle C)
  298.         
  299.         MOVE.L        (A7)+,A0            ; restore A0
  300.     }
  301.     /* sound should start at byte 36 */
  302. }
  303.  
  304. static    void    FillInNumSample(    soundHandle, numSamples)
  305.     Handle        soundHandle;
  306.     long        numSamples;
  307. {
  308.     asm
  309.     {
  310.         MOVE.L    A0,-(A7)            ;    save A0
  311.         MOVE.L    soundHandle,A0        ;    handle to data
  312.         MOVE.L    (A0),A0                ;    deref
  313.         MOVE.L    numSamples,18(A0)    ;    fill it in
  314.         MOVE.L    (A7)+,A0            ;    restore A0
  315.     }
  316. }
  317.  
  318.  
  319. static    void Interrupts( setEm )
  320.     short    setEm;
  321. {
  322.     asm 
  323.     {
  324.         MOVE        setEm(A6),D0
  325.         BNE.S        @0
  326.  
  327.         ORI            #0x0700,SR            ; off
  328.         BRA.S        @1
  329. @0
  330.         ANDI        #0xF8FF,SR            ; on
  331. @1
  332.     }
  333. }
  334.  
  335.